package cn.tradewin.advisor.pages.workflow;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.shiro.subject.Subject;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.EventConstants;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.StreamResponse;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.beaneditor.BeanModel;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.InjectService;
import org.apache.tapestry5.services.BeanModelSource;
import org.apache.tapestry5.services.Response;
import org.slf4j.Logger;
import org.tynamo.security.services.SecurityService;

import cn.tradewin.advisor.exceptions.DBException;
import cn.tradewin.advisor.persist.model.Vacation;
import cn.tradewin.advisor.persist.model.VacationWrapper;

public class ApproveVacation {

	@Property
	List<VacationWrapper> vacations;

	@Property
	VacationWrapper current;

	@Inject
	private SecurityService securityService;

	@Inject
	private ProcessEngine processEngine;
	
	@Inject
	private TaskService taskService;
	
	@Inject
	private RuntimeService runtimeService;

	@Inject
	private RepositoryService repositoryService;

	@Inject
	private Messages messages;

	@InjectService("ProcessEngineConfiguration")
	private StandaloneProcessEngineConfiguration processEngineConfig;
	
	@Inject
	private BeanModelSource beanModelSource;

	@Property
	private BeanModel<VacationWrapper> beanModel;

	@Property
	@Persist
	private String taskid;
	
	@Inject
	private ComponentResources _resources;
	

	public Link getChart() {
		return _resources.createEventLink("chart", false, null);
	}

	public StreamResponse onChart() {
		return new StreamResponse() {
			public String getContentType() {
				return "image/png";
			}
			public InputStream getStream() throws IOException {
				try {
//					ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("vacationRequest").latestVersion().singleResult();
					Task task = taskService.createTaskQuery().taskId(taskid).singleResult();
					String executionId = task.getExecutionId();
					ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(executionId).singleResult();
					BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
				    List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionId);

				    return new DefaultProcessDiagramGenerator().generateDiagram(
				    		bpmnModel, "png",
				    		activeActivityIds, Collections.<String>emptyList(), 
				    		processEngine.getProcessEngineConfiguration().getActivityFontName(), 
				    		processEngine.getProcessEngineConfiguration().getLabelFontName(), 
				    		null, 1.0);
				  
				} catch (Exception ex) {
					throw new RuntimeException("Cannot read image file.", ex);
				}
			}

			public void prepareResponse(Response response) {
			}
		};
	}
	
	@Inject
	Logger log;

	@SetupRender
	void setupRender() throws DBException {
		beanModel = beanModelSource.createDisplayModel(VacationWrapper.class, messages);
		beanModel.add("action", null);
		beanModel.include("taskid", "accountId", "category", "motivation",
				"applyDate", "vacationDate", "start", "end", "status",
				"action");
	}

	@OnEvent(EventConstants.PREPARE_FOR_RENDER)
	void prepareForRender() {
		Subject subject = securityService.getSubject();
		if (subject.hasRole("PM")) {
			List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("manager").list();
			if (tasks != null && tasks.size() > 0) {
				vacations = new ArrayList<VacationWrapper>();
				for (Task task : tasks) {
					log.info("owner = " + task.getOwner());
					log.info("assignee = " + task.getAssignee());
					VacationWrapper vw = null;
					String taskid = task.getId();
					Vacation v = (Vacation) taskService.getVariable(taskid, "vacation");
					if (v != null) {
						vw = new VacationWrapper();
						vw.setTaskid(taskid);
						vw.setAccountId(v.getAccountId());
						vw.setApplyDate(v.getApplyDate());
						vacations.add(vw);
					}
				}
			}
		}
	}

	public boolean isEmpty() {
		return vacations == null || vacations.size() == 0;
	}
	
	public boolean isDetail() {
		return taskid == null || taskid.length() == 0;
	}

	public void onConfirm(String taskid) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("vacationApproved", "false");
		param.put("managerMotivation", "job is not finished");
		taskService.complete(taskid, param);
	}
	
	public void onDetail(String taskid) {
	    this.taskid = taskid;	
	}
}